package pub.fjf.tools;

import java.io.UnsupportedEncodingException;

public class Base64 {
	private static byte pre1=0b00111111;
	private static byte pre2=0b00001111;
	private static byte pre3=0b00000011;
	
	public static byte[] code(byte[] data) {
		int length=0,i,rest;
		byte[] b64=new byte[data.length*4/3+3];
		for(i=0;i<data.length-2;i+=3) {
			b64[length]=(byte) ((data[i]>>>2)&pre1);
			b64[length+1]=(byte) (((data[i]<<4)|((data[i+1]>>>4)&pre2))&pre1);
			b64[length+2]=(byte) (((data[i+1]<<2)|((data[i+2]>>>6)&pre3))&pre1);
			b64[length+3]=(byte) (data[i+2]&pre1);
			length+=4;
		}
		rest=data.length%3;
		if(rest>0){
			b64[length]=(byte) ((data[i]>>>2)&pre1);
			b64[length+1]=(byte) (((data[i+0])<<4)&pre1);
			b64[length+2]=64;
			b64[length+3]=64;
			if(rest>1){
				b64[length+1]=(byte) (b64[length+1]|((data[i+1])>>>4)&pre2);
				b64[length+2]=(byte) ((data[i+1])<<2&pre1);
			}
			length+=4;
		}
		for(i=0;i<length;i++){
			if(b64[i]<26){
				b64[i]+='A';
			}else if(b64[i]<52){
				b64[i]+='a'-26;
			}else if(b64[i]<62){
				b64[i]+='0'-52;
			}else if(b64[i]==62){
				b64[i]='+';
			}else if(b64[i]==63){
				b64[i]='/';
			}else{
				b64[i]='=';
			}
		}
		byte[] result=new byte[length];
		for(i=0;i<length;i++) {
			result[i]=b64[i];
		}
		return result;
	}
	public static String code(String data,String charset) {
		try {
			return new String(code(data.getBytes(charset)));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	public static byte[] encode(byte[] data) {
		int length=0,i;
		byte[] b64=new byte[data.length];
		for(i=0;i<b64.length;i++){
			if(data[i]=='='){
				b64[i]=0;
			}else if(data[i]=='/'||data[i]=='_'){
				b64[i]=63;
			}else if(data[i]=='+'||data[i]=='-'){
				b64[i]=62;
			}else if(data[i]>='0'&&data[i]<='9'){
				b64[i]=(byte) (data[i]+52-'0');
			}else if(data[i]>='a'&&data[i]<='z'){
				b64[i]=(byte) (data[i]+26-'a');
			}else if(data[i]>='A'&&data[i]<='Z'){
				b64[i]=(byte) (data[i]-'A');
			}
		}
		byte[] b=new byte[b64.length*3/4+4];
		for(i=0;i<b64.length-3;i+=4){
			b[length]=(byte) (b64[i]<<2|((b64[i+1]>>4)&pre2));
			b[length+1]=(byte) (b64[i+1]<<4|((b64[i+2]>>2)&pre1));
			b[length+2]=(byte) (b64[i+2]<<6|b64[i+3]);
			length+=3;
		}
		for(i=data.length-1;data[i]=='=';i--){
			length--;
		}
		byte[] result=new byte[length];
		for(i=0;i<length;i++) {
			result[i]=b[i];
		}
		return result;
	}
	public static byte[] encode(String data) {
		return encode(data.getBytes());
	}
}
